Skip to content

Conversation

Jakeii
Copy link
Member

@Jakeii Jakeii commented Aug 5, 2025

Co-authored-by: Imogen Hardy [email protected]

What does this change?

This is based off @i-hardy's work that was integrated into our proof of concept branch for the new framework.

Adds a "beta" client for detecting if a user is in a test and/or variant, so that behaviour/rendering can be changed if a user is in said test/variant.

Client side tests are read from the gu_client_ab_tests cookie, and server side tests read from serverSideABTests on the data from frontend/window.

There's a react hook for use in DCR, as well as a method on the window for other bundles such as commercial to use. The hook works both client and server side, when running client side it will return both server and client side tests, but when used server side will only return server side tests.

Why?

As all test participation is calculated at the edge, the current frameworks use of @guardian/ab-core is no longer needed, with the Ophan reporting integrated here in DCR.

We've created a new "beta" client so that we can compare the old and new frameworks behaviour.

Copy link

github-actions bot commented Aug 5, 2025

@Jakeii Jakeii changed the title Add application code for reading new ab test framework state Client for reading new ab test framework state Aug 5, 2025
Copy link

github-actions bot commented Aug 7, 2025

@Jakeii Jakeii changed the title Client for reading new ab test framework state Client for reading Fastly dictionary ab test state Aug 8, 2025
@Jakeii Jakeii force-pushed the jlk/beta-ab-testing-client branch from 098ff9a to c77cfc8 Compare August 8, 2025 10:00
@Jakeii Jakeii marked this pull request as ready for review August 8, 2025 10:04
@Jakeii Jakeii requested a review from a team as a code owner August 8, 2025 10:04
Copy link

github-actions bot commented Aug 8, 2025

Hello 👋! When you're ready to run Chromatic, please apply the run_chromatic label to this PR.

You will need to reapply the label each time you want to run Chromatic.

Click here to see the Chromatic project.

@cemms1 cemms1 requested a review from a team August 8, 2025 10:33
@Jakeii Jakeii requested a review from Copilot August 8, 2025 12:26
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a new beta A/B testing client framework for reading Fastly dictionary A/B test state, designed to replace the current @guardian/ab-core framework. The implementation supports both server-side and client-side A/B testing with separate data sources and provides a React hook for DCR usage.

  • Adds BetaABTests class for managing A/B test participation with server-side and client-side support
  • Implements useBetaAB React hook for accessing A/B test state in components
  • Integrates client-side A/B test reading from cookies and server-side tests from configuration

Reviewed Changes

Copilot reviewed 30 out of 61 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/experiments/lib/beta-ab-tests.ts Core beta A/B testing class implementation with server/client-side logic
src/client/abTesting.ts Client-side A/B test initialization and cookie parsing logic
src/lib/useAB.ts React hooks for beta A/B testing integration
src/components/SetABTests.importable.tsx Integration of beta A/B tests into existing setup flow
src/types/config.ts Type definition updates for new serverSideABTests property
Multiple schema/render files Addition of serverSideABTests configuration throughout the application

export const useBetaAB = (): BetaABTestAPI | undefined => {
const { data } = useSWRImmutable(
'beta-ab-tests',
() => new Promise<BetaABTestAPI>(() => {}),
Copy link
Preview

Copilot AI Aug 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This promise never resolves, which means the hook will always return undefined. The promise should either resolve with a real implementation or use a different approach to initialize the data.

Suggested change
() => new Promise<BetaABTestAPI>(() => {}),
() => undefined,

Copilot uses AI. Check for mistakes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want it to never resolve as it will be replaced.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was copied from the current client useAB added in #4200, it is initially set to a promise that won't resolve, when SetABTests.importable runs it sets it to the initialised ab test API.

It needs to be a promise, not sure if it necessarily needs to be a promise that doesn't resolve. Promise.resolve(undefined) might do the trick too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to leave a comment explaining that? If you will keep it unresolved or even if you resolve it with undefined a comment would be good.

Comment on lines +60 to +64
/**
* The 'abTests' is for use by external scripts that need to
* access A/B test information. Do not use this directly
* in DCR, instead use the `useAB` hook as it is csr/ssr aware.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice 👏

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I second this 👏🏼

export const useBetaAB = (): BetaABTestAPI | undefined => {
const { data } = useSWRImmutable(
'beta-ab-tests',
() => new Promise<BetaABTestAPI>(() => {}),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work?

@Jakeii
Copy link
Member Author

Jakeii commented Aug 12, 2025

I would suggest adding a comment here initially, explaining what's going on and then convert to a lib later on if required?

Yup good idea 👍

@guardian guardian deleted a comment from Copilot AI Aug 14, 2025
Copy link
Contributor

@deedeeh deedeeh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing work @Jakeii 👏🏼👏🏼 I have left one tiny comment just for clarification purposes whether you will not resolve the promise or resolve it as you suggested.

@Jakeii Jakeii added the run_chromatic Runs chromatic when label is applied label Aug 27, 2025
@github-actions github-actions bot removed the run_chromatic Runs chromatic when label is applied label Aug 27, 2025
@Jakeii Jakeii requested a review from arelra August 28, 2025 10:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants